package com.code.platform.common.log;

import com.code.platform.common.utils.ClassUtils;
import com.code.platform.common.utils.ThrowableUtils;
import com.google.common.base.Strings;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.Random;

/**
 * User: xuning
 * Date: 12-6-12
 * Time: 下午3:31
 * Description:
 */
@Aspect
@Component
public class CommonLogAspect {
    Logger logger = LoggerFactory.getLogger(CommonLogAspect.class);

    @Around("execution(* com.code..service..*(..))&& @annotation(rl)")
    public Object log(ProceedingJoinPoint point, CommonLog rl) throws Throwable {
        StringBuilder msg = new StringBuilder();
        String methodInfo = generateLogMsg(point, rl);
        msg.append("methodInfo:").append(methodInfo);
        long beginMillis = System.currentTimeMillis();
        try {
            Object result = point.proceed();
            long endMillis = System.currentTimeMillis();
            String returnInfo = ClassUtils.getObjectLogInfo(result);
            if(!Strings.isNullOrEmpty(returnInfo) && returnInfo.length() > 500){
                returnInfo = returnInfo.substring(0, 500);
            }
            logger.info(msg.append(" |return: 【").append(returnInfo).append("】|useTime:【").append(
                endMillis - beginMillis).append("ms】").toString());
            return result;
        } catch (Throwable t) {
            long endMillis = System.currentTimeMillis();
            String throwableInfo = ThrowableUtils.getStackTraceAsString(t);
            logger.error(msg.append("|useTime:【").append(endMillis - beginMillis).append("ms】")
                    .append("|EXCEPTION:【").append(throwableInfo).append("】").toString());
            throw t;
        }
    }

    private String generateLogMsg(JoinPoint jp, CommonLog rl) {
        String threadInfo = "【threadId:" + Thread.currentThread().getId() + "】";
        String methodId = "【callTime:" + System.currentTimeMillis() + "-" + new Random().nextInt(
            1000) + "】";
        String methodSimpleName = "method【" + jp.getSignature().toShortString() + "()】";

        Object[] parames = jp.getArgs();//获取目标方法体参数
        String params = parseParames(parames); //解析目标方法体的参数
        String className = jp.getTarget().getClass().getSimpleName();//获取目标类名
        String desc = rl == null ? "" : rl.desc();
        return threadInfo + methodId + methodSimpleName + "Desc【" + desc + "】Class【" + className + "】,Params【" + params + "】";
    }

    /**
     * 解析方法参数
     *
     * @param params 方法参数
     * @return 解析后的方法参数
     */
    private String parseParames(Object[] params) {
        StringBuilder sb = new StringBuilder();
        for (Object param : params) {
            if (param != null) {
                String parameter = param.toString();
                if(parameter.length() > 200){
                    parameter = parameter.substring(0, 200);
                }
                sb.append(param.getClass().getSimpleName()).append(":").append(parameter).append(" ");
            }
        }
        String result = sb.toString();
        result = result.replaceAll("(\"\\w+\":\"\",)", "");
        result = result.replaceAll("(,\"\\w+\":\"\")", "");
        return result;
    }
}
